/**
 * Copyright(c)2012 Beijing PeaceMap Co.,Ltd.
 * All right reserved. 
 */
package com.pmc.dwa.security.intercept;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

/**
 * @description 访问决策器，决定某个用户具有的角色，是否有足够的权限去访问某个资源 ;做最终的访问控制决定
 * @author aokunsang
 * @date 2013-1-6
 */
public class PmcAccessDecisionManager implements AccessDecisionManager {

	/* 认证用户是否具有权限访问该url地址   [没有分配权限的地址，所有角色都可以进入]*/
	@SuppressWarnings("unchecked")
	@Override
	public void decide(Authentication authentication, Object obj,
			Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
			InsufficientAuthenticationException {
		
		if(configAttributes==null || configAttributes.isEmpty()) return;    //throw new AccessDeniedException("没有访问权限！");
		
		 //用户所有的权限
		Collection<SimpleGrantedAuthority> auths = (Collection<SimpleGrantedAuthority>)authentication.getAuthorities();
		//没有分配权限
		if(auths == null || auths.isEmpty()) throw new AccessDeniedException("该用户没有访问权限！");
		
		Iterator<ConfigAttribute> iter = configAttributes.iterator();
		while(iter.hasNext()){
			String needRole = iter.next().getAttribute();
			for(GrantedAuthority ga:auths){
				if(needRole.equals(ga.getAuthority())){
					return;
				}
			}
		}
		throw new AccessDeniedException("该用户没有访问权限！");
	}

	/* 启动时候被AbstractSecurityInterceptor调用，决定AccessDecisionManager是否可以执行传递ConfigAttribute。 */
	@Override
	public boolean supports(ConfigAttribute configAttribute) {
		return true;
	}

	/* 被安全拦截器实现调用，包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型 */
	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}
}
